package r3.flow;

import r3.cluster.router.RouterEntity;
import r3.common.R3Url;
import r3.common.R3Utils;
import r3.rpc.RpcRequest;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 参数分流
 */
public abstract class OutHandler {

    public List<RouterEntity> out(Method method, Object[] parameters, List<R3Url> urls) throws Throwable {
        List<RouterEntity> entities = new ArrayList<>();
        List<Object[]> objectsList = null;
        if (parameters != null && parameters.length != 0) {
            objectsList = this.shard(parameters, urls.size());
            if (objectsList.size() != urls.size()) {
                throw new Exception("Parameters are not evenly distributed of method " + method.getName());
            }
        }
        for (int i = 0, l = urls.size(); i < l; i++) {
            RouterEntity entity = new RouterEntity();
            entity.setUrl(urls.get(i));
            RpcRequest request = new RpcRequest();
            request.setRpcId(R3Utils.randomUUID());
            request.setParameterTypes(method.getParameterTypes());
            request.setArguments((objectsList == null || objectsList.size() == 0) ? parameters : objectsList.get(i));
            request.setBeanId(urls.get(i).getBeanId());
            request.setMethodName(method.getName());
            entity.setRequest(request);
            entities.add(entity);
        }
        return entities;
    }

    /**
     * 用户自定义分流策略
     *
     * @param parameters 方法参数列表
     * @param shardCount 当前分片数
     * @return
     * @throws Throwable
     */
    public abstract List<Object[]> shard(Object[] parameters, int shardCount) throws Throwable;


}
